

from rest_framework import viewsets, generics, status
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser
from rest_framework.decorators import action
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from .models import Book, Author, Publisher, BookLoan, BookReview
from .serializers import (
    BookSerializer, AuthorSerializer, PublisherSerializer,
    BookLoanSerializer, BookReviewSerializer
)
from .filters import BookFilter
from django.db.models import Count, Q
from django.db import transaction
from django.utils import timezone
import logging

logger = logging.getLogger(__name__)

class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.annotate(book_count=Count('books'))
    serializer_class = AuthorSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter, OrderingFilter]
    search_fields = ['name', 'email']
    ordering_fields = ['name', 'book_count']
    
    @action(detail=True, methods=['get'])
    def books(self, request, pk=None):
        author = self.get_object()
        books = author.books.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

class PublisherViewSet(viewsets.ModelViewSet):
    queryset = Publisher.objects.all()
    serializer_class = PublisherSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [SearchFilter]
    search_fields = ['name', 'code']

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.select_related('author', 'publisher').prefetch_related('reviews')
    serializer_class = BookSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_class = BookFilter
    search_fields = ['title', 'author__name', 'isbn']
    ordering_fields = ['title', 'publish_date', 'price']
    
    def get_queryset(self):
        queryset = super().get_queryset()
        status = self.request.query_params.get('status')
        if status:
            queryset = queryset.filter(status=status)
        return queryset
    
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        book = self.get_object()
        book.status = 'published'
        book.save()
        return Response({'status': 'book published'})
    
    @action(detail=False, methods=['get'])
    def recent(self, request):
        recent_books = self.get_queryset().order_by('-publish_date')[:5]
        serializer = self.get_serializer(recent_books, many=True)
        return Response(serializer.data)

class BookLoanViewSet(viewsets.ModelViewSet):
    queryset = BookLoan.objects.select_related('book', 'user')
    serializer_class = BookLoanSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['book', 'user', 'return_date']
    
    def get_queryset(self):
        queryset = super().get_queryset()
        if not self.request.user.is_staff:
            queryset = queryset.filter(user=self.request.user)
        return queryset
    
    @action(detail=True, methods=['post'])
    def return_book(self, request, pk=None):
        loan = self.get_object()
        if loan.return_date is not None:
            return Response(
                {'error': 'Book already returned'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        loan.return_date = timezone.now().date()
        loan.save()
        return Response({'status': 'book returned'})

class BookReviewViewSet(viewsets.ModelViewSet):
    queryset = BookReview.objects.select_related('user', 'book')
    serializer_class = BookReviewSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        queryset = super().get_queryset()
        book_id = self.request.query_params.get('book')
        if book_id:
            queryset = queryset.filter(book_id=book_id)
        return queryset
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

class BulkUpdatePricesView(generics.GenericAPIView):
    permission_classes = [IsAdminUser]
    
    def post(self, request, *args, **kwargs):
        book_ids = request.data.get('book_ids', [])
        price_increase = float(request.data.get('price_increase', 0))
        
        try:
            with transaction.atomic():
                books = Book.objects.filter(id__in=book_ids)
                books.update(price=F('price') + price_increase)
                return Response({'updated': len(book_ids)})
        except Exception as e:
            logger.error(f"Error in bulk update: {str(e)}")
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )